home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DDJ0192.ARJ / DFLAT.192 < prev    next >
Text File  |  1991-11-21  |  36KB  |  1,126 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4. [LISTING ONE]
  5.  
  6. /* ------------- editbox.c ------------ */
  7. #include "dflat.h"
  8.  
  9. #define EditBufLen(wnd) (isMultiLine(wnd) ? EDITLEN : ENTRYLEN)
  10. #define SetLinePointer(wnd, ln) (wnd->CurrLine = ln)
  11. #define isWhite(c)     ((c)==' '||(c)=='\n')
  12. /* ---------- local prototypes ----------- */
  13. static void SaveDeletedText(WINDOW, char *, int);
  14. static void Forward(WINDOW);
  15. static void Backward(WINDOW);
  16. static void End(WINDOW);
  17. static void Home(WINDOW);
  18. static void Downward(WINDOW);
  19. static void Upward(WINDOW);
  20. static void StickEnd(WINDOW);
  21. static void NextWord(WINDOW);
  22. static void PrevWord(WINDOW);
  23. static void ResetEditBox(WINDOW);
  24. static void ModTextPointers(WINDOW, int, int);
  25. /* -------- local variables -------- */
  26. static int KeyBoardMarking, ButtonDown;
  27. static int TextMarking;
  28. static int ButtonX, ButtonY;
  29. static int PrevY = -1;
  30. /* ----------- CREATE_WINDOW Message ---------- */
  31. static int CreateWindowMsg(WINDOW wnd)
  32. {
  33.     int rtn = BaseWndProc(EDITBOX, wnd, CREATE_WINDOW, 0, 0);
  34.     wnd->MaxTextLength = MAXTEXTLEN+1;
  35.     wnd->textlen = EditBufLen(wnd);
  36.     wnd->InsertMode = TRUE;
  37.     ResetEditBox(wnd);
  38.     return rtn;
  39. }
  40. /* ----------- SETTEXT Message ---------- */
  41. static int SetTextMsg(WINDOW wnd, PARAM p1)
  42. {
  43.     int rtn = FALSE;
  44.     if (strlen((char *)p1) <= wnd->MaxTextLength)    {
  45.         rtn = BaseWndProc(EDITBOX, wnd, SETTEXT, p1, 0);
  46.         wnd->CurrLine = 0;
  47.     }
  48.     return rtn;
  49. }
  50. /* ----------- ADDTEXT Message ---------- */
  51. static int AddTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  52. {
  53.     int rtn = FALSE;
  54.     if (strlen((char *)p1)+wnd->textlen <= wnd->MaxTextLength) {
  55.         rtn = BaseWndProc(EDITBOX, wnd, ADDTEXT, p1, p2);
  56.         if (rtn != FALSE)    {
  57.             if (!isMultiLine(wnd))    {
  58.                 wnd->CurrLine = 0;
  59.                 wnd->CurrCol = strlen((char *)p1);
  60.                 if (wnd->CurrCol >= ClientWidth(wnd))    {
  61.                     wnd->wleft = wnd->CurrCol-ClientWidth(wnd);
  62.                     wnd->CurrCol -= wnd->wleft;
  63.                 }
  64.                 wnd->BlkEndCol = wnd->CurrCol;
  65.                 SendMessage(wnd, KEYBOARD_CURSOR,
  66.                                      WndCol, wnd->WndRow);
  67.             }
  68.         }
  69.     }
  70.     return rtn;
  71. }
  72. /* ----------- GETTEXT Message ---------- */
  73. static int GetTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  74. {
  75.     char *cp1 = (char *)p1;
  76.     char *cp2 = wnd->text;
  77.     if (cp2 != NULL)    {
  78.         while (p2-- && *cp2 && *cp2 != '\n')
  79.             *cp1++ = *cp2++;
  80.         *cp1 = '\0';
  81.         return TRUE;
  82.     }
  83.     return FALSE;
  84. }
  85. /* ----------- SETTEXTLENGTH Message ---------- */
  86. static int SetTextLengthMsg(WINDOW wnd, unsigned int len)
  87. {
  88.     if (++len < MAXTEXTLEN)    {
  89.         wnd->MaxTextLength = len;
  90.         if (len < wnd->textlen)    {
  91.             if ((wnd->text=realloc(wnd->text, len+2)) != NULL) {
  92.                 wnd->textlen = len;
  93.                 *((wnd->text)+len) = '\0';
  94.                 *((wnd->text)+len+1) = '\0';
  95.                 BuildTextPointers(wnd);
  96.             }
  97.         }
  98.         return TRUE;
  99.     }
  100.     return FALSE;
  101. }
  102. /* ----------- KEYBOARD_CURSOR Message ---------- */
  103. static int KeyboardCursorMsg(WINDOW wnd, PARAM p1, PARAM p2)
  104. {
  105.     int rtn;
  106.     wnd->CurrCol = (int)p1 + wnd->wleft;
  107.     wnd->WndRow = (int)p2;
  108.     wnd->CurrLine = (int)p2 + wnd->wtop;
  109.     rtn = BaseWndProc(EDITBOX, wnd, KEYBOARD_CURSOR, p1, p2);
  110.     if (wnd == inFocus && CharInView(wnd, (int)p1, (int)p2))
  111.         SendMessage(NULL, SHOW_CURSOR, wnd->InsertMode, 0);
  112.     else SendMessage(NULL, HIDE_CURSOR, 0, 0);
  113.     return rtn;
  114. }
  115. /* ----------- SIZE Message ---------- */
  116. int SizeMsg(WINDOW wnd, PARAM p1, PARAM p2)
  117. {
  118.     int rtn = BaseWndProc(EDITBOX, wnd, SIZE, p1, p2);
  119.     if (WndCol > ClientWidth(wnd)-1)
  120.         wnd->CurrCol = ClientWidth(wnd)-1 + wnd->wleft;
  121.     if (wnd->WndRow > ClientHeight(wnd)-1)    {
  122.         wnd->WndRow = ClientHeight(wnd)-1;
  123.         SetLinePointer(wnd, wnd->WndRow+wnd->wtop);
  124.     }
  125.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  126.     return rtn;
  127. }
  128. /* ----------- SCROLL Message ---------- */
  129. static int ScrollMsg(WINDOW wnd, PARAM p1)
  130. {
  131.     int rtn = FALSE;
  132.     if (isMultiLine(wnd))    {
  133.         rtn = BaseWndProc(EDITBOX,wnd,SCROLL,p1,0);
  134.         if (rtn != FALSE)    {
  135.             if (p1)    {
  136.                 /* -------- scrolling up --------- */
  137.                 if (wnd->WndRow == 0)    {
  138.                     wnd->CurrLine++;
  139.                     StickEnd(wnd);
  140.                 }
  141.                 else
  142.                     --wnd->WndRow;
  143.             }
  144.             else    {
  145.                 /* -------- scrolling down --------- */
  146.                 if (wnd->WndRow == ClientHeight(wnd)-1)    {
  147.                     if (wnd->CurrLine > 0)
  148.                         --wnd->CurrLine;
  149.                     StickEnd(wnd);
  150.                 }
  151.                 else
  152.                     wnd->WndRow++;
  153.             }
  154.             SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
  155.         }
  156.     }
  157.     return rtn;
  158. }
  159. /* ----------- HORIZSCROLL Message ---------- */
  160. static int HorizScrollMsg(WINDOW wnd, PARAM p1)
  161. {
  162.     int rtn = FALSE;
  163.     char *currchar = CurrChar;
  164.     if (!(p1 &&
  165.             wnd->CurrCol == wnd->wleft && *currchar == '\n'))  {
  166.         rtn = BaseWndProc(EDITBOX, wnd, HORIZSCROLL, p1, 0);
  167.         if (rtn != FALSE)    {
  168.             if (wnd->CurrCol < wnd->wleft)
  169.                 wnd->CurrCol++;
  170.             else if (WndCol == ClientWidth(wnd))
  171.                 --wnd->CurrCol;
  172.             SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
  173.         }
  174.     }
  175.     return rtn;
  176. }
  177. /* ----------- SCROLLPAGE Message ---------- */
  178. static int ScrollPageMsg(WINDOW wnd, PARAM p1)
  179. {
  180.     int rtn = FALSE;
  181.     if (isMultiLine(wnd))    {
  182.         rtn = BaseWndProc(EDITBOX, wnd, SCROLLPAGE, p1, 0);
  183.         SetLinePointer(wnd, wnd->wtop+wnd->WndRow);
  184.         StickEnd(wnd);
  185.         SendMessage(wnd, KEYBOARD_CURSOR,WndCol, wnd->WndRow);
  186.     }
  187.     return rtn;
  188. }
  189. /* ----------- HORIZSCROLLPAGE Message ---------- */
  190. static int HorizPageMsg(WINDOW wnd, PARAM p1)
  191. {
  192.     int rtn = BaseWndProc(EDITBOX, wnd, HORIZPAGE, p1, 0);
  193.     if ((int) p1 == FALSE)    {
  194.         if (wnd->CurrCol > wnd->wleft+ClientWidth(wnd)-1)
  195.             wnd->CurrCol = wnd->wleft+ClientWidth(wnd)-1;
  196.     }
  197.     else if (wnd->CurrCol < wnd->wleft)
  198.         wnd->CurrCol = wnd->wleft;
  199.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  200.     return rtn;
  201. }
  202. /* ----- Extend the marked block to the new x,y position ---- */
  203. static void ExtendBlock(WINDOW wnd, int x, int y)
  204. {
  205.     int bbl, bel;
  206.     int ptop = min(wnd->BlkBegLine, wnd->BlkEndLine);
  207.     int pbot = max(wnd->BlkBegLine, wnd->BlkEndLine);
  208.     char *lp = TextLine(wnd, wnd->wtop+y);
  209.     int len = (int) (strchr(lp, '\n') - lp);
  210.     x = min(x, len-wnd->wleft);
  211.     wnd->BlkEndCol = x+wnd->wleft;
  212.     wnd->BlkEndLine = y+wnd->wtop;
  213.     bbl = min(wnd->BlkBegLine, wnd->BlkEndLine);
  214.     bel = max(wnd->BlkBegLine, wnd->BlkEndLine);
  215.     while (ptop < bbl)    {
  216.         WriteTextLine(wnd, NULL, ptop, FALSE);
  217.         ptop++;
  218.     }
  219.     for (y = bbl; y <= bel; y++)
  220.         WriteTextLine(wnd, NULL, y, FALSE);
  221.     while (pbot > bel)    {
  222.         WriteTextLine(wnd, NULL, pbot, FALSE);
  223.         --pbot;
  224.     }
  225. }
  226. /* ----------- LEFT_BUTTON Message ---------- */
  227. static int LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  228. {
  229.     int MouseX = (int) p1 - GetClientLeft(wnd);
  230.     int MouseY = (int) p2 - GetClientTop(wnd);
  231.     RECT rc = ClientRect(wnd);
  232.     char *lp;
  233.     int len;
  234.     if (KeyBoardMarking)
  235.         return TRUE;
  236.     if (WindowMoving || WindowSizing)
  237.         return FALSE;
  238.     if (isMultiLine(wnd))    {
  239.         if (TextMarking)    {
  240.             if (!InsideRect(p1, p2, rc))    {
  241.                 if ((int)p1 == GetLeft(wnd))
  242.                     if (SendMessage(wnd, HORIZSCROLL, 0, 0))
  243.                         ExtendBlock(wnd, MouseX-1, MouseY);
  244.                 if ((int)p1 == GetRight(wnd))
  245.                     if (SendMessage(wnd, HORIZSCROLL, TRUE, 0))
  246.                         ExtendBlock(wnd, MouseX+1, MouseY);
  247.                 if ((int)p2 == GetTop(wnd))
  248.                     if (SendMessage(wnd, SCROLL, FALSE, 0))
  249.                         ExtendBlock(wnd, MouseX, MouseY+1);
  250.                 if ((int)p2 == GetBottom(wnd))
  251.                     if (SendMessage(wnd, SCROLL, TRUE, 0))
  252.                         ExtendBlock(wnd, MouseX, MouseY-1);
  253.                 SendMessage(wnd, PAINT, 0, 0);
  254.             }
  255.             return TRUE;
  256.         }
  257.         if (!InsideRect(p1, p2, rc))
  258.             return FALSE;
  259.         if (TextBlockMarked(wnd))    {
  260.             ClearTextBlock(wnd);
  261.             SendMessage(wnd, PAINT, 0, 0);
  262.         }
  263.         if (wnd->wlines)    {
  264.             if (MouseY > wnd->wlines-1)
  265.                 return TRUE;
  266.             lp = TextLine(wnd, MouseY+wnd->wtop);
  267.             len = (int) (strchr(lp, '\n') - lp);
  268.             MouseX = min(MouseX, len);
  269.             if (MouseX < wnd->wleft)    {
  270.                 MouseX = 0;
  271.                 SendMessage(wnd, KEYBOARD, HOME, 0);
  272.             }
  273.             ButtonDown = TRUE;
  274.             ButtonX = MouseX;
  275.             ButtonY = MouseY;
  276.         }
  277.         else
  278.             MouseX = MouseY = 0;
  279.         wnd->WndRow = MouseY;
  280.         SetLinePointer(wnd, MouseY+wnd->wtop);
  281.     }
  282.     if (isMultiLine(wnd) ||
  283.         (!TextBlockMarked(wnd)
  284.             && MouseX+wnd->wleft < strlen(wnd->text)))
  285.         wnd->CurrCol = MouseX+wnd->wleft;
  286.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  287.     return TRUE;
  288. }
  289. /* ----------- MOUSE_MOVED Message ---------- */
  290. static int MouseMovedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  291. {
  292.     int MouseX = (int) p1 - GetClientLeft(wnd);
  293.     int MouseY = (int) p2 - GetClientTop(wnd);
  294.     RECT rc = ClientRect(wnd);
  295.     if (!InsideRect(p1, p2, rc))
  296.         return FALSE;
  297.     if (MouseY > wnd->wlines-1)
  298.         return FALSE;
  299.     if (ButtonDown)    {
  300.         SetAnchor(wnd, ButtonX+wnd->wleft, ButtonY+wnd->wtop);
  301.         TextMarking = TRUE;
  302.         SendMessage(NULL,MOUSE_TRAVEL,
  303.                 (PARAM)&WindowRect(wnd),0);
  304.         ButtonDown = FALSE;
  305.     }
  306.     if (TextMarking && !(WindowMoving || WindowSizing))    {
  307.         ExtendBlock(wnd, MouseX, MouseY);
  308.         return TRUE;
  309.     }
  310.     return FALSE;
  311. }
  312. static void StopMarking(WINDOW wnd)
  313. {
  314.     TextMarking = FALSE;
  315.     if (wnd->BlkBegLine > wnd->BlkEndLine)    {
  316.         swap(wnd->BlkBegLine, wnd->BlkEndLine);
  317.         swap(wnd->BlkBegCol, wnd->BlkEndCol);
  318.     }
  319.     if (wnd->BlkBegLine == wnd->BlkEndLine &&
  320.             wnd->BlkBegCol > wnd->BlkEndCol)
  321.         swap(wnd->BlkBegCol, wnd->BlkEndCol);
  322. }
  323. /* ----------- BUTTON_RELEASED Message ---------- */
  324. static int ButtonReleasedMsg(WINDOW wnd)
  325. {
  326.     if (isMultiLine(wnd))    {
  327.         ButtonDown = FALSE;
  328.         if (TextMarking && !(WindowMoving || WindowSizing))  {
  329.             /* release the mouse ouside the edit box */
  330.             SendMessage(NULL, MOUSE_TRAVEL, 0, 0);
  331.             StopMarking(wnd);
  332.             return TRUE;
  333.         }
  334.         else
  335.             PrevY = -1;
  336.     }
  337.     return FALSE;
  338. }
  339. /* ---- Process text block keys for multiline text box ---- */
  340. static void DoMultiLines(WINDOW wnd, int c, PARAM p2)
  341. {
  342.     if (isMultiLine(wnd))    {
  343.         if ((int)p2 & (LEFTSHIFT | RIGHTSHIFT))    {
  344.             int kx, ky;
  345.             SendMessage(NULL, CURRENT_KEYBOARD_CURSOR,
  346.                 (PARAM) &kx, (PARAM) &ky);
  347.             kx -= GetClientLeft(wnd);
  348.             ky -= GetClientTop(wnd);
  349.             switch (c)    {
  350.                 case HOME:
  351.                 case END:
  352.                 case CTRL_HOME:
  353.                 case CTRL_END:
  354.                 case PGUP:
  355.                 case PGDN:
  356.                 case CTRL_PGUP:
  357.                 case CTRL_PGDN:
  358.                 case UP:
  359.                 case DN:
  360.                 case FWD:
  361.                 case BS:
  362.                 case CTRL_FWD:
  363.                 case CTRL_BS:
  364.                     if (!KeyBoardMarking)    {
  365.                         if (TextBlockMarked(wnd))    {
  366.                             ClearTextBlock(wnd);
  367.                             SendMessage(wnd, PAINT, 0, 0);
  368.                         }
  369.                         KeyBoardMarking = TextMarking = TRUE;
  370.                         SetAnchor(wnd, kx+wnd->wleft,
  371.                                                 ky+wnd->wtop);
  372.                     }
  373.                     break;
  374.                 default:
  375.                     break;
  376.             }
  377.         }
  378.     }
  379. }
  380. /* ---------- page/scroll keys ----------- */
  381. static int DoScrolling(WINDOW wnd, int c, PARAM p2)
  382. {
  383.     switch (c)    {
  384.         case PGUP:
  385.         case PGDN:
  386.             if (isMultiLine(wnd))
  387.                 BaseWndProc(EDITBOX, wnd, KEYBOARD, c, p2);
  388.             break;
  389.         case CTRL_PGUP:
  390.         case CTRL_PGDN:
  391.             BaseWndProc(EDITBOX, wnd, KEYBOARD, c, p2);
  392.             break;
  393.         case HOME:
  394.             Home(wnd);
  395.             break;
  396.         case END:
  397.             End(wnd);
  398.             break;
  399.         case CTRL_FWD:
  400.             NextWord(wnd);
  401.             break;
  402.         case CTRL_BS:
  403.             PrevWord(wnd);
  404.             break;
  405.         case CTRL_HOME:
  406.             if (isMultiLine(wnd))    {
  407.                 SendMessage(wnd, SCROLLDOC, TRUE, 0);
  408.                 wnd->CurrLine = 0;
  409.                 wnd->WndRow = 0;
  410.             }
  411.             Home(wnd);
  412.             break;
  413.         case CTRL_END:
  414.             if (isMultiLine(wnd) && wnd->wlines > 0)    {
  415.                 SendMessage(wnd, SCROLLDOC, FALSE, 0);
  416.                 SetLinePointer(wnd, wnd->wlines-1);
  417.                 wnd->WndRow =
  418.                     min(ClientHeight(wnd)-1, wnd->wlines-1);
  419.                 Home(wnd);
  420.             }
  421.             End(wnd);
  422.             break;
  423.         case UP:
  424.             if (isMultiLine(wnd))
  425.                 Upward(wnd);
  426.             break;
  427.         case DN:
  428.             if (isMultiLine(wnd))
  429.                 Downward(wnd);
  430.             break;
  431.         case FWD:
  432.             Forward(wnd);
  433.             break;
  434.         case BS:
  435.             Backward(wnd);
  436.             break;
  437.         default:
  438.             return FALSE;
  439.     }
  440.     if (!KeyBoardMarking && TextBlockMarked(wnd))    {
  441.         ClearTextBlock(wnd);
  442.         SendMessage(wnd, PAINT, 0, 0);
  443.     }
  444.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  445.     return TRUE;
  446. }
  447. /* -------------- Del key ---------------- */
  448. static int DelKey(WINDOW wnd)
  449. {
  450.     char *currchar = CurrChar;
  451.     int repaint = *currchar == '\n';
  452.     if (TextBlockMarked(wnd))    {
  453.         SendMessage(wnd, COMMAND, ID_DELETETEXT, 0);
  454.         SendMessage(wnd, PAINT, 0, 0);
  455.         return TRUE;
  456.     }
  457.     if (*(currchar+1) == '\0')
  458.         return TRUE;
  459.     strcpy(currchar, currchar+1);
  460.     if (repaint)    {
  461.         BuildTextPointers(wnd);
  462.         SendMessage(wnd, PAINT, 0, 0);
  463.     }
  464.     else    {
  465.         ModTextPointers(wnd, wnd->CurrLine+1, -1);
  466.         WriteTextLine(wnd, NULL, wnd->WndRow+wnd->wtop, FALSE);
  467.     }
  468.     wnd->TextChanged = TRUE;
  469.     return FALSE;
  470. }
  471. /* ------------ Tab key ------------ */
  472. static int TabKey(WINDOW wnd, PARAM p2)
  473. {
  474.     if (isMultiLine(wnd))    {
  475.         int insmd = wnd->InsertMode;
  476.         do  {
  477.             char *cc = CurrChar+1;
  478.             if (!insmd && *cc == '\0')
  479.                 break;
  480.             if (wnd->textlen == wnd->MaxTextLength)
  481.                 break;
  482.             SendMessage(wnd,KEYBOARD,insmd ? ' ' : FWD,0);
  483.         } while (wnd->CurrCol % cfg.Tabs);
  484.         return TRUE;
  485.     }
  486.     PostMessage(GetParent(wnd), KEYBOARD, '\t', p2);
  487.     return FALSE;
  488. }
  489. /* --------- All displayable typed keys ------------- */
  490. static void KeyTyped(WINDOW wnd, int c)
  491. {
  492.     char *currchar = CurrChar;
  493.     if ((c != '\n' && c < ' ') || (c & 0x1000))
  494.         /* ---- not recognized by editor --- */
  495.         return;
  496.     if (!isMultiLine(wnd) && TextBlockMarked(wnd))    {
  497.         ResetEditBox(wnd);
  498.         currchar = CurrChar;
  499.     }
  500.     if (*currchar == '\0')    {
  501.         /* ---- typing at end of text ---- */
  502.         if (currchar == wnd->text+wnd->MaxTextLength)    {
  503.             /* ---- typing at the end of maximum buffer ---- */
  504.             beep();
  505.             return;
  506.         }
  507.         /* --- insert a newline at end of text --- */
  508.         *currchar = '\n';
  509.         *(currchar+1) = '\0';
  510.         BuildTextPointers(wnd);
  511.     }
  512.     /* --- displayable char or newline --- */
  513.     if (c == '\n' || wnd->InsertMode ||    *currchar == '\n') {
  514.         /* ------ inserting the keyed character ------ */
  515.         if (wnd->text[wnd->textlen-1] != '\0')    {
  516.             /* --- the current text buffer is full --- */
  517.             if (wnd->textlen == wnd->MaxTextLength)    {
  518.                 /* --- text buffer is at maximum size --- */
  519.                 beep();
  520.                 return;
  521.             }
  522.             /* ---- increase the text buffer size ---- */
  523.             wnd->textlen += GROWLENGTH;
  524.             /* --- but not above maximum size --- */
  525.             if (wnd->textlen > wnd->MaxTextLength)
  526.                 wnd->textlen = wnd->MaxTextLength;
  527.             wnd->text = realloc(wnd->text, wnd->textlen+2);
  528.             wnd->text[wnd->textlen-1] = '\0';
  529.             currchar = CurrChar;
  530.         }
  531.         memmove(currchar+1, currchar, strlen(currchar)+1);
  532.         ModTextPointers(wnd, wnd->CurrLine+1, 1);
  533.         if (isMultiLine(wnd) && wnd->wlines > 1)
  534.             wnd->textwidth = max(wnd->textwidth,
  535.                 (int) (TextLine(wnd, wnd->CurrLine+1)-
  536.                 TextLine(wnd, wnd->CurrLine)));
  537.         else
  538.             wnd->textwidth = max(wnd->textwidth,
  539.                 strlen(wnd->text));
  540.         WriteTextLine(wnd, NULL,
  541.             wnd->wtop+wnd->WndRow, FALSE);
  542.     }
  543.     /* ----- put the char in the buffer ----- */
  544.     *currchar = c;
  545.     wnd->TextChanged = TRUE;
  546.     if (c == '\n')    {
  547.         wnd->wleft = 0;
  548.         BuildTextPointers(wnd);
  549.         End(wnd);
  550.         Forward(wnd);
  551.         SendMessage(wnd, PAINT, 0, 0);
  552.         return;
  553.     }
  554.     /* ---------- test end of window --------- */
  555.     if (WndCol == ClientWidth(wnd)-1)    {
  556.         int dif;
  557.         char *cp = currchar;
  558.         while (*cp != ' ' && cp != TextLine(wnd, wnd->CurrLine))
  559.             --cp;
  560.         if (!isMultiLine(wnd) ||
  561.             cp == TextLine(wnd, wnd->CurrLine) ||
  562.                 !wnd->WordWrapMode)
  563.             SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  564.         else    {
  565.             dif = 0;
  566.             if (c != ' ')    {
  567.                 dif = (int) (currchar - cp);
  568.                 wnd->CurrCol -= dif;
  569.                 SendMessage(wnd, KEYBOARD, DEL, 0);
  570.                 --dif;
  571.             }
  572.             SendMessage(wnd, KEYBOARD, '\r', 0);
  573.             currchar = CurrChar;
  574.             wnd->CurrCol = dif;
  575.             if (c == ' ')
  576.                 return;
  577.         }
  578.     }
  579.     /* ------ display the character ------ */
  580.     SetStandardColor(wnd);
  581.     PutWindowChar(wnd, c, WndCol, wnd->WndRow);
  582.     /* ----- advance the pointers ------ */
  583.     wnd->CurrCol++;
  584. }
  585. /* ------------ screen changing key strokes ------------- */
  586. static int DoKeyStroke(WINDOW wnd, int c, PARAM p2)
  587. {
  588.     switch (c)    {
  589.         case RUBOUT:
  590.             Backward(wnd);
  591.         case DEL:
  592.             if (DelKey(wnd))
  593.                 return TRUE;
  594.             break;
  595.         case CTRL_FIVE:    /* same as Shift+Tab */
  596.             if (!((int)p2 & (LEFTSHIFT | RIGHTSHIFT)))
  597.                 break;
  598.         case '\t':
  599.             if (TabKey(wnd, p2))
  600.                 return TRUE;
  601.             break;
  602.         case '\r':
  603.             if (!isMultiLine(wnd))    {
  604.                 PostMessage(GetParent(wnd), KEYBOARD, c, p2);
  605.                 break;
  606.             }
  607.             c = '\n';
  608.         default:
  609.             if (TextBlockMarked(wnd))    {
  610.                 SendMessage(wnd, COMMAND, ID_DELETETEXT, 0);
  611.                 SendMessage(wnd, PAINT, 0, 0);
  612.             }
  613.             KeyTyped(wnd, c);
  614.             break;
  615.     }
  616.     return FALSE;
  617. }
  618. /* ----------- KEYBOARD Message ---------- */
  619. static int KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  620. {
  621.     int c = (int) p1;
  622.     if (WindowMoving || WindowSizing || ((int)p2 & ALTKEY))
  623.         return FALSE;
  624.     switch (c)    {
  625.         /* --- these keys get processed by lower classes --- */
  626.         case ESC:
  627.         case F1:
  628.         case F2:
  629.         case F3:
  630.         case F4:
  631.         case F5:
  632.         case F6:
  633.         case F7:
  634.         case F8:
  635.         case F9:
  636.         case F10:
  637.         case INS:
  638.         case SHIFT_INS:
  639.         case SHIFT_DEL:
  640.             return FALSE;
  641.         /* --- these keys get processed here --- */
  642.         case CTRL_FWD:
  643.         case CTRL_BS:
  644.         case CTRL_HOME:
  645.         case CTRL_END:
  646.         case CTRL_PGUP:
  647.         case CTRL_PGDN:
  648.             break;
  649.         default:
  650.             /* other ctrl keys get processed by lower classes */
  651.             if ((int)p2 & CTRLKEY)
  652.                 return FALSE;
  653.             /* --- all other keys get processed here --- */
  654.             break;
  655.     }
  656.     DoMultiLines(wnd, c, p2);
  657.     if (DoScrolling(wnd, c, p2))    {
  658.         if (KeyBoardMarking)
  659.             ExtendBlock(wnd, WndCol, wnd->WndRow);
  660.     }
  661.     else if (!TestAttribute(wnd, READONLY))    {
  662.         DoKeyStroke(wnd, c, p2);
  663.         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  664.     }
  665.     return TRUE;
  666. }
  667. /* ----------- SHIFT_CHANGED Message ---------- */
  668. static void ShiftChangedMsg(WINDOW wnd, PARAM p1)
  669. {
  670.     if (!((int)p1 & (LEFTSHIFT | RIGHTSHIFT)) &&
  671.                                    KeyBoardMarking)    {
  672.         StopMarking(wnd);
  673.         KeyBoardMarking = FALSE;
  674.     }
  675. }
  676. /* ----------- ID_DELETETEXT Command ---------- */
  677. static void DeleteTextCmd(WINDOW wnd)
  678. {
  679.     if (TextBlockMarked(wnd))    {
  680.         char *bbl=TextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
  681.         char *bel=TextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
  682.         int len = (int) (bel - bbl);
  683.         SaveDeletedText(wnd, bbl, len);
  684.         wnd->TextChanged = TRUE;
  685.         strcpy(bbl, bel);
  686.         wnd->CurrLine = TextLineNumber(wnd, bbl-wnd->BlkBegCol);
  687.         wnd->CurrCol = wnd->BlkBegCol;
  688.         wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
  689.         if (wnd->WndRow < 0)    {
  690.             wnd->wtop = wnd->BlkBegLine;
  691.             wnd->WndRow = 0;
  692.         }
  693.         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  694.         ClearTextBlock(wnd);
  695.         BuildTextPointers(wnd);
  696.     }
  697. }
  698. /* ----------- ID_CLEAR Command ---------- */
  699. static void ClearCmd(WINDOW wnd)
  700. {
  701.     if (TextBlockMarked(wnd))    {
  702.         char *bbl=TextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
  703.         char *bel=TextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
  704.         int len = (int) (bel - bbl);
  705.         SaveDeletedText(wnd, bbl, len);
  706.         wnd->CurrLine = TextLineNumber(wnd, bbl);
  707.         wnd->CurrCol = wnd->BlkBegCol;
  708.         wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
  709.         if (wnd->WndRow < 0)    {
  710.             wnd->WndRow = 0;
  711.             wnd->wtop = wnd->BlkBegLine;
  712.         }
  713.         /* ------ change all text lines in block to \n ----- */
  714.         while (bbl < bel)    {
  715.             char *cp = strchr(bbl, '\n');
  716.             if (cp > bel)
  717.                 cp = bel;
  718.             strcpy(bbl, cp);
  719.             bel -= (int) (cp - bbl);
  720.             bbl++;
  721.         }
  722.         ClearTextBlock(wnd);
  723.         BuildTextPointers(wnd);
  724.         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  725.         SendMessage(wnd, PAINT, 0, 0);
  726.         wnd->TextChanged = TRUE;
  727.     }
  728. }
  729. /* ----------- ID_UNDO Command ---------- */
  730. static void UndoCmd(WINDOW wnd)
  731. {
  732.     if (wnd->DeletedText != NULL)    {
  733.         PasteText(wnd, wnd->DeletedText, wnd->DeletedLength);
  734.         free(wnd->DeletedText);
  735.         wnd->DeletedText = NULL;
  736.         wnd->DeletedLength = 0;
  737.         SendMessage(wnd, PAINT, 0, 0);
  738.     }
  739. }
  740. /* ----------- ID_PARAGRAPH Command ---------- */
  741. static void ParagraphCmd(WINDOW wnd)
  742. {
  743.     int bc, ec, fl, el, Blocked;
  744.     char *bl, *bbl, *bel, *bb;
  745.  
  746.     el = wnd->BlkEndLine;
  747.     ec = wnd->BlkEndCol;
  748.     if (!TextBlockMarked(wnd))    {
  749.         Blocked = FALSE;
  750.         /* ---- forming paragraph from cursor position --- */
  751.         fl = wnd->wtop + wnd->WndRow;
  752.         bbl = bel = bl = TextLine(wnd, wnd->CurrLine);
  753.         if ((bc = wnd->CurrCol) >= ClientWidth(wnd))
  754.             bc = 0;
  755.         Home(wnd);
  756.         /* ---- locate the end of the paragraph ---- */
  757.         while (*bel)    {
  758.             int blank = TRUE;
  759.             char *bll = bel;
  760.             /* --- blank line marks end of paragraph --- */
  761.             while (*bel && *bel != '\n')    {
  762.                 if (*bel != ' ')
  763.                     blank = FALSE;
  764.                 bel++;
  765.             }
  766.             if (blank)    {
  767.                 bel = bll;
  768.                 break;
  769.             }
  770.             if (*bel)
  771.                 bel++;
  772.         }
  773.         if (bel == bbl)    {
  774.             SendMessage(wnd, KEYBOARD, DN, 0);
  775.             return;
  776.         }
  777.         if (*bel == '\0')
  778.             --bel;
  779.         if (*bel == '\n')
  780.             --bel;
  781.     }
  782.     else    {
  783.         /* ---- forming paragraph from marked block --- */
  784.         Blocked = TRUE;
  785.         bbl = TextLine(wnd, wnd->BlkBegLine) + wnd->BlkBegCol;
  786.         bel = TextLine(wnd, wnd->BlkEndLine) + wnd->BlkEndCol;
  787.         fl = wnd->BlkBegLine;
  788.         bc = wnd->CurrCol = wnd->BlkBegCol;
  789.         wnd->CurrLine = fl;
  790.         if (fl < wnd->wtop)
  791.             wnd->wtop = fl;
  792.         wnd->WndRow = fl - wnd->wtop;
  793.         SendMessage(wnd, KEYBOARD, '\r', 0);
  794.         el++, fl++;
  795.         if (bc != 0)    {
  796.             SendMessage(wnd, KEYBOARD, '\r', 0);
  797.             el++, fl ++;
  798.         }
  799.         bc = 0;
  800.         bl = TextLine(wnd, fl);
  801.         wnd->CurrLine = fl;
  802.         bbl = bl + bc;
  803.         bel = TextLine(wnd, el) + ec;
  804.     }
  805.     /* --- change all newlines in block to spaces --- */
  806.     while (CurrChar < bel)    {
  807.         if (*CurrChar == '\n')    {
  808.             *CurrChar = ' ';
  809.             wnd->CurrLine++;
  810.             wnd->CurrCol = 0;
  811.         }
  812.         else
  813.             wnd->CurrCol++;
  814.     }
  815.     /* ---- insert newlines at new margin boundaries ---- */
  816.     bb = bbl;
  817.     while (bbl < bel)    {
  818.         bbl++;
  819.         if ((int)(bbl - bb) == ClientWidth(wnd)-1)    {
  820.             while (*bbl != ' ' && bbl > bb)
  821.                 --bbl;
  822.             if (*bbl != ' ')    {
  823.                 bbl = strchr(bbl, ' ');
  824.                 if (bbl == NULL || bbl >= bel)
  825.                     break;
  826.             }
  827.             *bbl = '\n';
  828.             bb = bbl+1;
  829.         }
  830.     }
  831.     ec = (int)(bel - bb);
  832.     BuildTextPointers(wnd);
  833.     if (Blocked)    {
  834.         /* ---- position cursor at end of new paragraph ---- */
  835.         if (el < wnd->wtop ||
  836.                 wnd->wtop + ClientHeight(wnd) < el)
  837.             wnd->wtop = el-ClientHeight(wnd);
  838.         if (wnd->wtop < 0)
  839.             wnd->wtop = 0;
  840.         wnd->WndRow = el - wnd->wtop;
  841.         wnd->CurrLine = el;
  842.         wnd->CurrCol = ec;
  843.         SendMessage(wnd, KEYBOARD, '\r', 0);
  844.         SendMessage(wnd, KEYBOARD, '\r', 0);
  845.     }
  846.     else    {
  847.         /* --- put cursor back at beginning --- */
  848.         wnd->CurrLine = TextLineNumber(wnd, bl);
  849.         wnd->CurrCol = bc;
  850.         if (fl < wnd->wtop)
  851.             wnd->wtop = fl;
  852.         wnd->WndRow = fl - wnd->wtop;
  853.     }
  854.     SendMessage(wnd, PAINT, 0, 0);
  855.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  856.     wnd->TextChanged = TRUE;
  857.     BuildTextPointers(wnd);
  858. }
  859. /* ----------- COMMAND Message ---------- */
  860. static int CommandMsg(WINDOW wnd, PARAM p1)
  861. {
  862.     switch ((int)p1)    {
  863.         case ID_DELETETEXT:
  864.             DeleteTextCmd(wnd);
  865.             return TRUE;
  866.         case ID_CLEAR:
  867.             ClearCmd(wnd);
  868.             return TRUE;
  869.         case ID_UNDO:
  870.             UndoCmd(wnd);
  871.             return TRUE;
  872.         case ID_PARAGRAPH:
  873.             ParagraphCmd(wnd);
  874.             return TRUE;
  875.         default:
  876.             break;
  877.     }
  878.     return FALSE;
  879. }
  880. /* ---------- CLOSE_WINDOW Message ----------- */
  881. static void CloseWindowMsg(WINDOW wnd)
  882. {
  883.     SendMessage(NULL, HIDE_CURSOR, 0, 0);
  884.     if (wnd->DeletedText != NULL)
  885.         free(wnd->DeletedText);
  886. }
  887. /* ------- Window processing module for EDITBOX class ------ */
  888. int EditBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  889. {
  890.     int rtn;
  891.     switch (msg)    {
  892.         case CREATE_WINDOW:
  893.             return CreateWindowMsg(wnd);
  894.         case ADDTEXT:
  895.             return AddTextMsg(wnd, p1, p2);
  896.         case SETTEXT:
  897.             return SetTextMsg(wnd, p1);
  898.         case CLEARTEXT:
  899.             ResetEditBox(wnd);
  900.             break;
  901.         case GETTEXT:
  902.             return GetTextMsg(wnd, p1, p2);
  903.         case SETTEXTLENGTH:
  904.             return SetTextLengthMsg(wnd, (unsigned) p1);
  905.         case KEYBOARD_CURSOR:
  906.             return KeyboardCursorMsg(wnd, p1, p2);
  907.         case SETFOCUS:
  908.         case PAINT:
  909.         case MOVE:
  910.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  911.             SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
  912.             return rtn;
  913.         case SIZE:
  914.             return SizeMsg(wnd, p1, p2);
  915.         case SCROLL:
  916.             return ScrollMsg(wnd, p1);
  917.         case HORIZSCROLL:
  918.             return HorizScrollMsg(wnd, p1);
  919.         case SCROLLPAGE:
  920.             return ScrollPageMsg(wnd, p1);
  921.         case HORIZPAGE:
  922.             return HorizPageMsg(wnd, p1);
  923.         case LEFT_BUTTON:
  924.             if (LeftButtonMsg(wnd, p1, p2))
  925.                 return TRUE;
  926.             break;
  927.         case MOUSE_MOVED:
  928.             if (MouseMovedMsg(wnd, p1, p2))
  929.                 return TRUE;
  930.             break;
  931.         case BUTTON_RELEASED:
  932.             if (ButtonReleasedMsg(wnd))
  933.                 return TRUE;
  934.             break;
  935.         case KEYBOARD:
  936.             if (KeyboardMsg(wnd, p1, p2))
  937.                 return TRUE;
  938.             break;
  939.         case SHIFT_CHANGED:
  940.             ShiftChangedMsg(wnd, p1);
  941.             break;
  942.         case COMMAND:
  943.             if (CommandMsg(wnd, p1))
  944.                 return TRUE;
  945.             break;
  946.         case CLOSE_WINDOW:
  947.             CloseWindowMsg(wnd);
  948.             break;
  949.         default:
  950.             break;
  951.     }
  952.     return BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  953. }
  954. /* ------ save deleted text for the Undo command ------ */
  955. static void SaveDeletedText(WINDOW wnd, char *bbl, int len)
  956. {
  957.     wnd->DeletedLength = len;
  958.     if ((wnd->DeletedText=realloc(wnd->DeletedText,len))!=NULL)
  959.         memmove(wnd->DeletedText, bbl, len);
  960. }
  961. /* ---- cursor right key: right one character position ---- */
  962. static void Forward(WINDOW wnd)
  963. {
  964.     char *cc = CurrChar+1;
  965.     if (*cc == '\0')
  966.         return;
  967.     if (*CurrChar == '\n')    {
  968.         Home(wnd);
  969.         Downward(wnd);
  970.     }
  971.     else    {
  972.         wnd->CurrCol++;
  973.         if (WndCol == ClientWidth(wnd))
  974.             SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  975.     }
  976. }
  977. /* ----- stick the moving cursor to the end of the line ---- */
  978. static void StickEnd(WINDOW wnd)
  979. {
  980.     char *cp = TextLine(wnd, wnd->CurrLine);
  981.     char *cp1 = strchr(cp, '\n');
  982.     int len = cp1 ? (int) (cp1 - cp) : 0;
  983.     wnd->CurrCol = min(len, wnd->CurrCol);
  984.     if (wnd->wleft > wnd->CurrCol)    {
  985.         wnd->wleft = max(0, wnd->CurrCol - 4);
  986.         SendMessage(wnd, PAINT, 0, 0);
  987.     }
  988.     else if (wnd->CurrCol-wnd->wleft >= ClientWidth(wnd))    {
  989.         wnd->wleft = wnd->CurrCol - (ClientWidth(wnd)-1);
  990.         SendMessage(wnd, PAINT, 0, 0);
  991.     }
  992. }
  993. /* --------- cursor down key: down one line --------- */
  994. static void Downward(WINDOW wnd)
  995. {
  996.     if (isMultiLine(wnd) &&
  997.             wnd->WndRow+wnd->wtop+1 < wnd->wlines)  {
  998.         wnd->CurrLine++;
  999.         if (wnd->WndRow == ClientHeight(wnd)-1)
  1000.             SendMessage(wnd, SCROLL, TRUE, 0);
  1001.         wnd->WndRow++;
  1002.         StickEnd(wnd);
  1003.     }
  1004. }
  1005. /* -------- cursor up key: up one line ------------ */
  1006. static void Upward(WINDOW wnd)
  1007. {
  1008.     if (isMultiLine(wnd) && wnd->CurrLine != 0)    {
  1009.         if (wnd->CurrLine > 0)
  1010.             --wnd->CurrLine;
  1011.         if (wnd->WndRow == 0)
  1012.             SendMessage(wnd, SCROLL, FALSE, 0);
  1013.         --wnd->WndRow;
  1014.         StickEnd(wnd);
  1015.     }
  1016. }
  1017. /* ---- cursor left key: left one character position ---- */
  1018. static void Backward(WINDOW wnd)
  1019. {
  1020.     if (wnd->CurrCol)    {
  1021.         if (wnd->CurrCol-- <= wnd->wleft)
  1022.             if (wnd->wleft != 0)
  1023.                 SendMessage(wnd, HORIZSCROLL, FALSE, 0);
  1024.     }
  1025.     else if (isMultiLine(wnd) && wnd->CurrLine != 0)    {
  1026.         Upward(wnd);
  1027.         End(wnd);
  1028.     }
  1029. }
  1030. /* -------- End key: to end of line ------- */
  1031. static void End(WINDOW wnd)
  1032. {
  1033.     while (*CurrChar && *CurrChar != '\n')
  1034.         ++wnd->CurrCol;
  1035.     if (WndCol >= ClientWidth(wnd))    {
  1036.         wnd->wleft = wnd->CurrCol - (ClientWidth(wnd)-1);
  1037.         SendMessage(wnd, PAINT, 0, 0);
  1038.     }
  1039. }
  1040. /* -------- Home key: to beginning of line ------- */
  1041. static void Home(WINDOW wnd)
  1042. {
  1043.     wnd->CurrCol = 0;
  1044.     if (wnd->wleft != 0)    {
  1045.         wnd->wleft = 0;
  1046.         SendMessage(wnd, PAINT, 0, 0);
  1047.     }
  1048. }
  1049. /* -- Ctrl+cursor right key: to beginning of next word -- */
  1050. static void NextWord(WINDOW wnd)
  1051. {
  1052.     int savetop = wnd->wtop;
  1053.     int saveleft = wnd->wleft;
  1054.     ClearVisible(wnd);
  1055.     while (!isWhite(*CurrChar))    {
  1056.         char *cc = CurrChar+1;
  1057.         if (*cc == '\0')
  1058.             break;
  1059.         Forward(wnd);
  1060.     }
  1061.     while (isWhite(*CurrChar))    {
  1062.         char *cc = CurrChar+1;
  1063.         if (*cc == '\0')
  1064.             break;
  1065.         Forward(wnd);
  1066.     }
  1067.     SetVisible(wnd);
  1068.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  1069.     if (wnd->wtop != savetop || wnd->wleft != saveleft)
  1070.         SendMessage(wnd, PAINT, 0, 0);
  1071. }
  1072. /* -- Ctrl+cursor left key: to beginning of previous word -- */
  1073. static void PrevWord(WINDOW wnd)
  1074. {
  1075.     int savetop = wnd->wtop;
  1076.     int saveleft = wnd->wleft;
  1077.     ClearVisible(wnd);
  1078.     Backward(wnd);
  1079.     while (isWhite(*CurrChar))    {
  1080.         if (wnd->CurrLine == 0 && wnd->CurrCol == 0)
  1081.             break;
  1082.         Backward(wnd);
  1083.     }
  1084.     while (!isWhite(*CurrChar))    {
  1085.         if (wnd->CurrLine == 0 && wnd->CurrCol == 0)
  1086.             break;
  1087.         Backward(wnd);
  1088.     }
  1089.     if (isWhite(*CurrChar))
  1090.         Forward(wnd);
  1091.     SetVisible(wnd);
  1092.     if (wnd->wleft != saveleft)
  1093.         if (wnd->CurrCol >= saveleft)
  1094.             if (wnd->CurrCol - saveleft < ClientWidth(wnd))
  1095.                 wnd->wleft = saveleft;
  1096.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  1097.     if (wnd->wtop != savetop || wnd->wleft != saveleft)
  1098.         SendMessage(wnd, PAINT, 0, 0);
  1099. }
  1100. /* ----- reset the text attributes of an EDITBOX ------- */
  1101. static void ResetEditBox(WINDOW wnd)
  1102. {
  1103.     unsigned blen = EditBufLen(wnd)+2;
  1104.     wnd->text = realloc(wnd->text, blen);
  1105.     memset(wnd->text, 0, blen);
  1106.     wnd->wlines = 0;
  1107.     wnd->CurrLine = 0;
  1108.     wnd->CurrCol = 0;
  1109.     wnd->WndRow = 0;
  1110.     wnd->wleft = 0;
  1111.     wnd->wtop = 0;
  1112.     wnd->textwidth = 0;
  1113.     wnd->TextChanged = FALSE;
  1114.     ClearTextPointers(wnd);
  1115.     ClearTextBlock(wnd);
  1116. }
  1117. /* ----- modify text pointers from a specified position
  1118.                 by a specified plus or minus amount ----- */
  1119. static void ModTextPointers(WINDOW wnd, int lineno, int var)
  1120. {
  1121.     while (lineno < wnd->wlines)
  1122.         *((wnd->TextPointers) + lineno++) += var;
  1123. }
  1124.  
  1125.  
  1126.